
#pragma once

#include "particle.h"

namespace physics {
	/////////////////////////////////////////
	// ParticleContact
	/////////////////////////////////////////
	// A ParticleContact object stores the relevant data 
	// for two objects in contact with one another, which
	// can then be resolved by a contact resolution
	// algorithm.

	// defined further below
	// need this so we can make it a friend class
	// to the ParticleContact class
	class ParticleContactResolver;

	class ParticleContact
	{
		
		

		// lets the ParticleContactResolver play
		// with the ParticleContact nicely
		friend ParticleContactResolver;

	public:
		// holds the Particles involved in the
		// contact. The second particle could be
		// NULL in the case where we not colliding
		// two particles (e.g. collision between a
		// box and the floor)
		Particle *particle[2];

		// the coefficient of restitution. Should be
		// based on the materials of the objects
		// involved and determined when this data is
		// created.
		real restitution;

		// the contact normal in world-coordinates.
		Vector3 contactNormal;
		
		// the penetration depth
		real penetration;
		
		// keeps track of how much the Particles have
		// moved during contact resolution
		Vector3 particleMovement[2];
	protected:
		// resolve the contact, based on the amount
		// of time that has passed
		void resolve(real dt);

		// determines the separating velocity of 
		// the two objects
		real calculateSeparatingVelocity() const;
		
	private:
		// handles impulse calculations
		void resolveVelocity(real dt);

		// handles interpenetration resolution
		void resolveInterpenetration(real dt);
	};

	/////////////////////////////////////////
	// ParticleContactResolver
	/////////////////////////////////////////
	// This object resolves ParticleContact objects
	class ParticleContactResolver
	{
	protected:
		unsigned iterationsAllowed; // the number of iterations allowed so we don't resolve contacts forever

		unsigned iterationsUsed; // the number of iterations used

	public:
		// creates a new resolver
		ParticleContactResolver(unsigned iterations);

		// sets the number of iterations that can be used
		void setIterations(unsigned iterations);

		// resolves a set of contacts for penetration and velocity
		void resolveContacts(ParticleContact *contactArray, unsigned numContacts, real dt);

	};

	class ParticleContactGenerator
	{
	public:
		// Stores the given contact structure which can
		// later be iterated
		// through and have all of the contacts resolved.
		// has a finite limit on the number of contacts
		// that can be resolved in a single timestep and 
		// returns the number of contacts that have so
		// far been written this timestep. Is an ABC for
		// more complex contact generation systems
		virtual unsigned addContact(ParticleContact *contact, unsigned limit) const = 0;
	};
}